﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using vJine.Core.ORM;
using vJine.Core.IoC;

namespace vJine.Core.ORM {
    public partial class Class<Tentity> {

        public class I : IDbCmd {
            public string table_name { get; protected set; }

            public I Into(string table) {
                if(this.table_name != table) {
                    this.table_name = table;
                    this.IsPrepared = false;
                }

                return this;
            }

            internal List<Property> keys = null;
            public I Keys(params Property[] Keys) {
                if (Keys == null || Keys.Length == 0) {
                    return this;
                }

                this.IsPrepared = false;
                if (this.keys == null) {
                    this.keys = new List<Property>();
                }
                for (int i = 0, len = Keys.Length; i < len; i++) {
                    this.keys.Add(Keys[i]);
                }

                return this;
            }

            public I Values(params Tentity[] Values) {
                return this.Values(false, Values);
            }

            public I Values(IList<Tentity> Values) {
                return this.Values(false, Values);
            }

            public I Values(bool Reset, IList<Tentity> Values) {
                for (int i = 0, len = Values.Count; i < len; i++) {
                    this.Values(Reset, Values[i]);
                }

                return this;
            }

            internal List<Tentity> values = new List<Tentity>();
            public I Values(bool Reset, params Tentity[] Values) {
                if (Reset) {
                    this.values.Clear();
                }

                if (Values == null || Values.Length == 0) {
                    return this;
                }

                for (int i = 0, len = Values.Length; i < len; i++) {
                    this.values.Add(Values[i]);
                }

                return this;
            }

            public bool IsPrepared { get; set; }
            DbCommand dbCmd { get; set; }
            internal Exec<Tentity, DbCommand> Pcopy { get; set; }

            public DbCommand Prepare(IDbAdapter adapter) {
                if (this.IsPrepared) {
                    return this.dbCmd;
                }

                if(string.IsNullOrEmpty(this.table_name)) {
                    this.table_name = Class<Tentity>.Name;
                }

                if (this.keys == null || this.keys.Count == 0) {
                    this.keys = adapter.GetProperties<Tentity>();
                }
                this.Pcopy = adapter.Get_I<Tentity>(this.keys);

                this.dbCmd = adapter.PrepareInsert<Tentity>(this.table_name, this.keys);
                this.IsPrepared = true; return this.dbCmd;
            }
        }

        public class D : IDbCmd {
            public string table_name { get; set; }

            public D From(string table) {
                if(this.table_name != table) {
                    this.table_name = table;
                    this.IsPrepared = false;
                }

                return this;
            }

            Where where = null;
            public D Where(Where where) {
                this.IsPrepared = false;
                this.where &= where;

                return this;
            }

            public bool IsPrepared { get; set; }
            DbCommand dbCmd { get; set; }

            public DbCommand Prepare(IDbAdapter adapter) {
                if (this.IsPrepared) {
                    return this.dbCmd;
                }

                if(string.IsNullOrEmpty(this.table_name)) {
                    this.table_name = Class<Tentity>.Name;
                }

                this.dbCmd =
                    adapter.PrepareDelete<Tentity>(this.table_name, this.where);

                this.IsPrepared = true; return this.dbCmd;
            }
        }

        public class U : IDbCmd {
            public string table_name { get; protected set; }

            public U Update(string table) {
                if(this.table_name != table) {
                    this.table_name = table;
                    this.IsPrepared = false;
                }

                return this;
            }

            Set set = null;
            public U Set(Set set) {
                this.IsPrepared = false;

                this.set &= set;

                return this;
            }

            Where where = null;
            public U Where(Where where) {
                this.IsPrepared = false;

                this.where &= where;

                return this;
            }

            public bool IsPrepared { get; set; }
            DbCommand dbCmd { get; set; }

            public DbCommand Prepare(IDbAdapter adapter) {
                if (this.IsPrepared) {
                    return this.dbCmd;
                }

                if(string.IsNullOrEmpty(this.table_name)) {
                    this.table_name = Class<Tentity>.Name;
                }

                this.dbCmd =
                    adapter.PrepareUpdate<Tentity>(this.table_name, this.set, this.where);

                this.IsPrepared = true; return this.dbCmd;
            }
        }

        public class Q : IDbCmd {
            public int Max { get; private set; }
            internal List<Property> keys = null;

            public Q Select(params Property[] Keys) {
                this.IsPrepared = false;

                this.Select(0, Keys);

                return this;
            }

            public Q Select(int max, params Property[] Keys) {
                this.IsPrepared = false;

                if (this.Max != max) {
                    this.IsPrepared = false;
                    this.Max = max;
                }

                if (Keys == null || Keys.Length == 0) {
                    return this;
                }
                if (this.keys == null) {
                    this.keys = new List<Property>();
                }

                this.Qcopy = null;
                for (int i = 0, len = Keys.Length; i < len; i++) {
                    this.keys.Add(Keys[i]);
                }

                return this;
            }

            public string table_name { get; protected set; }
            public Q From(string table) {
                if(this.table_name != table) {
                    this.table_name = table;
                    this.IsPrepared = false;
                }

                return this;
            }

            Where where = null;
            public Q Where(Where Where) {
                return this.Where(false, Where);
            }

            public Q Where(bool Reset, Where Where) {
                this.IsPrepared = false;

                if (Reset) {
                    this.where = null;
                }

                this.where &= Where;

                return this;
            }

            List<Class<Tentity>.Property> Orders { get; set; }
            public Q OrderBy(params Class<Tentity>.Property[] orders) {
                if (orders == null || orders.Length == 0) {
                    return this;
                }
                if (this.Orders == null) {
                    this.Orders = new List<Property>();
                }

                for (int i = 0, len = orders.Length; i < len; i++) {
                    Class<Tentity>.Property order_i = orders[i];
                    this.Orders.Add(order_i);                    
                }

                return this;
            }

            public bool IsPrepared { get; set; }
            DbCommand dbCmd { get; set; }

            internal Exec<DbDataReader, Tentity> Qcopy { get; set; }

            public DbCommand Prepare(IDbAdapter adapter) {
                if (this.IsPrepared) {
                    return this.dbCmd;
                }

                if(string.IsNullOrEmpty(this.table_name)) {
                    this.table_name = Class<Tentity>.Name;
                }

                if (this.keys == null || this.keys.Count == 0) {
                    this.keys = adapter.GetProperties<Tentity>();
                }

                if (this.Qcopy == null) {
                    this.Qcopy = adapter.Get_Q<Tentity>(this.keys);
                }
                this.dbCmd =
                    adapter.PrepareQuery<Tentity>(this.Max, this.keys, this.table_name, this.where,this.Orders);

                this.IsPrepared = true; return dbCmd;
            }
        }
    }
}